package com.lingfengerick.commons.encrypt.sm4tool;

import com.lingfengerick.commons.encrypt.sm4tool.toolkit.SM4Base;
import com.lingfengerick.commons.encrypt.sm4tool.toolkit.SM4_Context;
import org.apache.commons.lang3.StringUtils;

import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * SM4加解密策略类
 * @author lingfengerick
 * @since 2022/9/20 14:29
 */
public abstract class SM4SecretStrategy{

    boolean HEX_STRING = false;

    /**
     * 默认密钥
     */
    final static String DEFAULT_SECRET_KEY = "1zp3S9wZL5h1L&Jn";

    /**
     * 默认密钥进行加密
     *
     * @param dataStr 需要加密的字符串
     * @return 返回加密数据
     * @author lingfengerick
     * @since 2022/9/20  14:23
     */
    public String encryptDataToString(String dataStr){
        return encryptDataToString(dataStr , DEFAULT_SECRET_KEY);
    }

    /**
     * 指定密钥进行加密
     *
     * @param dataStr   需要加密的数据
     * @param secretKey 加密密钥
     * @return 返回加密数据
     * @author lingfengerick
     * @since 2022/9/20  14:24
     */
    public String encryptDataToString(String dataStr, String secretKey) {
        try {
            SM4_Context ctx = new SM4_Context();
            ctx.isPadding = true;
            ctx.mode = SM4Base.SM4_ENCRYPT;
            byte[] encrypted = getEncryptedByte(ctx , dataStr , secretKey);
            String cipherText = Base64.getEncoder().encodeToString(encrypted);
            if (cipherText != null && cipherText.trim().length() > 0) {
                Pattern p = Pattern.compile("\\s*|\t|\r|\n");
                Matcher m = p.matcher(cipherText);
                cipherText = m.replaceAll("");
            }
            return cipherText;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 采用默认的密钥进行解密
     * @param encryDataStr 加密数据
     * @return 解密后的数据
     * @author lingfengerick
     * @since 2022/9/20  14:27
     */
    public String decryptDataToString(String encryDataStr) {
        return decryptDataToString(encryDataStr , DEFAULT_SECRET_KEY);
    }

    /**
     * 指定密钥解密
     * @param encryDataStr 加密数据
     * @param secretKey    密钥
     * @return 解密数据
     * @author lingfengerick
     * @since 2022/9/20  14:28
     */
    public String decryptDataToString(String encryDataStr, String secretKey) {
        try {
            SM4_Context ctx = new SM4_Context();
            if (StringUtils.isEmpty(secretKey)){
                secretKey = DEFAULT_SECRET_KEY;
            }
            ctx.isPadding = true;
            ctx.mode = SM4Base.SM4_DECRYPT;
            byte[] decrypted = getDecryptedByte(ctx , encryDataStr , secretKey);
            return new String(decrypted);
        } catch (Exception e) {
            return null;
        }
    }

    /**
    * 将密钥转换为字节
    * @author  lingfengerick
    * @since  2022/9/20  14:36
    * @param hexString 字符串
    * @return 返回字节
    *
    */
    protected static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }

        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }
    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    abstract byte[] getEncryptedByte(SM4_Context sm4Context , String dataStr , String publicKey);

    abstract byte[] getDecryptedByte(SM4_Context sm4Context ,String encryptDataStr , String privateKey);
}
